package com.bac.rentmap.ad.batch.correction;

import java.util.Map;
import java.util.logging.Logger;

import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.PersistenceManager;

import com.bac.rentmap.ad.batch.Batchable;
import com.bac.rentmap.jdo.JdoSupport;

public class JdoCorrectionCalculator extends JdoSupport implements
        CorrectionCalculator {
    private static final Logger log = Logger
            .getLogger(JdoCorrectionCalculator.class.getName());

    private Map<String, Batchable> batchableMap;
    private static final double MIN_CORRECTION = 0.5;
    private static final double MAX_CORRECTION = 4;
    private static final double DESIRED_QUEUE_2_BATCH_SIZE_MIN_RATIO =0.5;
    private static final double DESIRED_QUEUE_2_BATCH_SIZE_MAX_RATIO = 1;
    private static final double NO_CORRECTION = 1;

    public double calculate(String uri) {
        PersistenceManager persistenceManager = getPersistenceManager();
        try {
            try {
                Correction res = persistenceManager.getObjectById(
                        Correction.class, uri);
                log.fine("Found correction " + res);
                return res.getValue();
            } catch (JDOObjectNotFoundException e) {
                return NO_CORRECTION;
            }
        } finally {
            persistenceManager.close();
        }
    }

    public boolean updateCorrection(String uri) {
        Batchable batchable = batchableMap.get(uri);
        int batchSize = batchable.getBatchSize();
        double queueSize = batchable.getQueueSize();
        double ratio = queueSize / batchSize;
        log.fine("Current ratio: " + ratio + " = " + queueSize + " / " + batchSize);
        double correction = calculate(uri);
        if (ratio < DESIRED_QUEUE_2_BATCH_SIZE_MIN_RATIO) {
            correction = (correction + MIN_CORRECTION) / 2;
        } else if (ratio > DESIRED_QUEUE_2_BATCH_SIZE_MAX_RATIO) {
            correction = (correction + MAX_CORRECTION) / 2;
        } else {
            return false;
        }
        log.info("Updating correction for " + uri + " to " + correction);
        saveCorrection(uri, correction);
        return true;
    }

    private void saveCorrection(String uri, double value) {
        PersistenceManager persistenceManager = getPersistenceManager();
        try {
            try {
                Correction correction = persistenceManager.getObjectById(
                        Correction.class, uri);
                correction.setValue(value);
            } catch (JDOObjectNotFoundException e) {
                persistenceManager.makePersistent(new Correction(uri, value));
            }
        } finally {
            persistenceManager.close();
        }

    }

    public void setBatchableMap(Map<String, Batchable> batchableMap) {
        this.batchableMap = batchableMap;
    }
}
